import java.util.Arrays;
import java.util.List;

/**
 * 哈夫曼编码解码类
 * 
 * @author yangmqglobe
 *
 */
class HuffmanEncode {
	// 哈夫曼编码表
	private List<String> huffCodes;
	// 与编码表一一对应的字符
	private String chars;
	// 哈夫曼树根节点
	private HuffmanNode root;

	/**
	 * 构造方法
	 * 
	 * @param huffmanTree
	 *            已经生成的哈夫曼树
	 * @param chars
	 *            与哈夫曼树对应的字符串
	 */
	public HuffmanEncode(HuffmanTree huffmanTree, String chars) {
		this.chars = chars;
		huffCodes = Arrays.asList(huffmanTree.createHuffCodes());
		root = huffmanTree.getRoot();
	}

	/**
	 * 判断某个字符串能否被编码，排除不能编码的字符
	 * 
	 * @param str
	 *            需要被编码的字符串
	 * @return 可以编码返回true，否则false
	 */
	public boolean canEncode(String str) {
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (chars.indexOf(c) < 0) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 将字符串进行编码
	 * 
	 * @param str
	 *            需要编码的字符串
	 * @return 编码结果
	 */
	public String encode(String str) {
		String code = "";
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			int index = chars.indexOf(c);
			code += huffCodes.get(index);
		}
		return code;
	}

	/**
	 * 对一段编码进行解码
	 * 
	 * @param code
	 *            编码
	 * @return 解码出来的字符串
	 */
	public String decode(String code) {
		String str = "";
		while (code.length() > 0) {// 当仍有未解码的编码
			String scode = "";
			HuffmanNode p = root;
			int i = 0;
			// 获得一个字符的编码
			while (p.getLchild() != null && p.getRchild() != null) {
				if (code.substring(i, i + 1).equals("1")) {
					p = p.getRchild();
				} else {
					p = p.getLchild();
				}
				i++;
			}
			scode = code.substring(0, i);
			int index = huffCodes.indexOf(scode);
			str += chars.substring(index, index + 1);
			// 切去已经解码的编码
			code = code.substring(scode.length());
		}
		return str;
	}
}
